const path = require('path')
const os = require('os')

//
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 本插件会将 CSS 提取到单独的文件中，为每个包含 CSS 的 JS 文件创建一个 CSS 文件，并且支持 CSS 和 SourceMaps 的按需加载。
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// // 这个插件使用 cssnano 优化和压缩 CSS。
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
// // 压缩JS webpack自带
const TerserWebpackPlugin = require('terser-webpack-plugin')

// 压缩图片
// const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin')
// const { extendDefaultPlugins } = require('svgo')

// 将已存在的单个文件或整个目录复制到生成目录。
const CopyPlugin = require('copy-webpack-plugin')

const { DefinePlugin } = require('webpack')
const { VueLoaderPlugin } = require('vue-loader')

// 获取CPU核数
const threads = os.cpus().length

function getStyleLoaders(pre) {
  return [
    MiniCssExtractPlugin.loader,
    'css-loader',
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: [
            [
              'postcss-preset-env'
            ]
          ]
        }
      }
    },
    pre
  ].filter(Boolean)
}

module.exports = {
  entry: './src/main.ts',
  output: {
    // __dirname, node.js的变量， 代表当前文件的文件夹目录
    path: path.resolve(__dirname, '../dist'), // 输出文件路径配置
    filename: 'static/js/[name].[contenthash:10].js', // 输出文件名
    chunkFilename: 'static/js/[name].[contenthash:10].chunk.js',
    assetModuleFilename: 'static/media/[hash:10][ext][query]',
    clean: true, // 自动将上次打包目录资源清空-无所谓哦
    // publicPath: './'
  },
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: getStyleLoaders()
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders('sass-loader')
      },
      {
        test: /\.less$/,
        use: getStyleLoaders('less-loader')
      },
      {
        test: /\.(png|jpe?g|gif|webp|svg)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            // 图片大小小于 10kb，就会被 base64 处理
            // 优点: 减少请求数量（减轻服务器压力）
            // 缺点：图片体积会更大（文件请求速度更慢)
            maxSize: 10 * 1024 // 10kb
          }
        }
        // generator: {
        //   // 给图片进行重命名
        //   // [hash:10]取图片的 hash 的前 10 位
        //   // [ext]取文件原来扩展名
        //   filename: 'static/images/[hash:10][ext][query]'
        // }
      },
      // 其他资源
      {
        test: /\.(ttf|woff2?|map3|avi)$/,
        type: 'asset/resource'

      },
      // babel 处理JS兼容
      {
        test: /\.(js|mjs|jsx|ts|tsx)$/,
        // exclude和include 只能用一种
        // exclude: /(node_modules|bower_components)/, // 不需要处理的
        include: path.resolve(__dirname, '../src'), // 只处理src下的文件，其他文件不处理
        use: {
          loader: 'babel-loader',
          options: {
            cacheDirectory: true, // 开启label 缓存
            cacheCompression: false // 关闭缓存文件压缩
          }
        }
      },
      {
        test: /.ts$/,
        use: {
          loader: 'ts-loader',
          options: {
            configFile: path.resolve(process.cwd(), 'tsconfig.json'),
            appendTsSuffixTo: [/\.vue$/],
          }
        },
        exclude: /node_modules/
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  // 用来设置引用模块
  resolve: {
    // 自动补全文件拓展名
    extensions: ['.vue', '.ts', '.js', '.jsx', '.tsx', '.json']
  },
  optimization: {
    minimizer: [
      // 压缩css
      new CssMinimizerPlugin(),
      // 压缩js
      new TerserWebpackPlugin({
        parallel: threads// 开启多进程和设置进程数量
      })
      // new ImageMinimizerPlugin({
      //   minimizerOptions: {
      //     // Lossless optimization with custom option
      //     // Feel free to experiment with options for better result for you
      //     plugins: [
      //       ['gifsicle', { interlaced: true }],
      //       ['jpegtran', { progressive: true }],
      //       ['optipng"', { optimizationLevel: 5 }],
      //       // Svgo configuration here https://github.com/svg/svgo#configuration
      //       [
      //         'svgo',
      //         {
      //           plugins: extendDefaultPlugins([
      //             {
      //               name: 'removeViewBox',
      //               active: false
      //             },
      //             {
      //               name: 'addAttributesToSVGElement',
      //               params: {
      //                 attr: [{ xmlns: 'http://www.w3.org/2000/svg' }]
      //               }
      //             }
      //           ])
      //         }
      //       ]
      //     ]
      //   }
      // })
    ],
    splitChunks: {
      chunks: 'all' // all 对所有模块进行分割
    },
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}.js`
    }
  },
  plugins: [
    // 模版，以public/index.html 文件创建新的HTML文件
    // 新的HTML文件特点 1.结构和原来一致 2.自动引入打包输出资源
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../public/index.html')
    }),

    new MiniCssExtractPlugin({
      // insert: '#some-element'
      filename: 'static/css/[name].[contenthash:10].css',
      chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
    }),
    new CopyPlugin({
      patterns: [{
        from: path.resolve(__dirname, '../public'),
        to: path.resolve(__dirname, '../dist'),
        globOptions: {
          // 忽略index.html 文件
          ignore: ['**/index.html']
        }

      }]
    }),
    new VueLoaderPlugin(),
    new DefinePlugin({
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false
    })
  ],
  mode: 'production' // 开发环境
}
